package com.pug.security.service.security;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.pug.security.pojo.SysLoginUser;
import com.pug.security.pojo.SysPermission;
import com.pug.security.pojo.SysRole;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.SpringSecurityCoreVersion;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.*;

public class LoginUser implements UserDetails {

    private Long userId;
    private String ip;
    private String ipLocation;
    private String os;
    private String currentTime;

    private String username;
    private String password;

    private SysLoginUser sysLoginUser;
    private Set<SysRole> roles;
    private Set<SysPermission> permissions;
    private Set<GrantedAuthority> authorities;

    public LoginUser(SysLoginUser sysLoginUser, Set<SysRole> roles, Set<SysPermission> permissions, Set<GrantedAuthority> authorities) {
        this.userId = sysLoginUser.getId();
        this.username = sysLoginUser.getUsername();
        this.password = sysLoginUser.getPassword();
        this.sysLoginUser = sysLoginUser;
        this.roles = roles;
        this.permissions = permissions;
        this.authorities = authorities;
    }

    @JsonIgnore
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    @JsonIgnore
    @Override
    public String getPassword() {
        return sysLoginUser.getPassword();
    }

    @Override
    public String getUsername() {
        return sysLoginUser.getUsername();
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isEnabled() {
        return true;
    }

    private static SortedSet<GrantedAuthority> sortAuthorities(Collection<? extends GrantedAuthority> authorities) {
        Assert.notNull(authorities, "Cannot pass a null GrantedAuthority collection");
        SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<>(new AuthorityComparator());
        for (GrantedAuthority grantedAuthority : authorities) {
            Assert.notNull(grantedAuthority, "GrantedAuthority list cannot contain any null elements");
            sortedAuthorities.add(grantedAuthority);
        }
        return sortedAuthorities;
    }

    private static class AuthorityComparator implements Comparator<GrantedAuthority>, Serializable {

        private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

        @Override
        public int compare(GrantedAuthority g1, GrantedAuthority g2) {
            // Neither should ever be null as each entry is checked before adding it to
            // the set. If the authority is null, it is a custom authority and should
            // precede others.
            if (g2.getAuthority() == null) {
                return -1;
            }
            if (g1.getAuthority() == null) {
                return 1;
            }
            return g1.getAuthority().compareTo(g2.getAuthority());
        }

    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getIpLocation() {
        return ipLocation;
    }

    public void setIpLocation(String ipLocation) {
        this.ipLocation = ipLocation;
    }

    public String getOs() {
        return os;
    }

    public void setOs(String os) {
        this.os = os;
    }

    public String getCurrentTime() {
        return currentTime;
    }

    public void setCurrentTime(String currentTime) {
        this.currentTime = currentTime;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @JsonIgnore
    public SysLoginUser getSysLoginUser() {
        return sysLoginUser;
    }

    public void setSysLoginUser(SysLoginUser sysLoginUser) {
        this.sysLoginUser = sysLoginUser;
    }

    public Set<SysRole> getRoles() {
        return roles;
    }

    public void setRoles(Set<SysRole> roles) {
        this.roles = roles;
    }



    public Set<SysPermission> getPermissions() {
        return permissions;
    }

    public void setPermissions(Set<SysPermission> permissions) {
        this.permissions = permissions;
    }

    public void setAuthorities(Set<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        LoginUser loginUser = (LoginUser) o;
        return Objects.equals(userId, loginUser.userId) &&
                Objects.equals(ip, loginUser.ip) &&
                Objects.equals(ipLocation, loginUser.ipLocation) &&
                Objects.equals(os, loginUser.os) &&
                Objects.equals(currentTime, loginUser.currentTime) &&
                Objects.equals(username, loginUser.username) &&
                Objects.equals(password, loginUser.password) &&
                Objects.equals(sysLoginUser, loginUser.sysLoginUser) &&
                Objects.equals(roles, loginUser.roles) &&
                Objects.equals(permissions, loginUser.permissions) &&
                Objects.equals(authorities, loginUser.authorities);
    }

    @Override
    public int hashCode() {
        return Objects.hash(userId, ip, ipLocation, os, currentTime, username, password, sysLoginUser, roles, permissions, authorities);
    }
}


